package com.lhkj.ct.meta.modules.report.word.group;

import cn.hutool.core.bean.BeanUtil;
import com.google.common.collect.Lists;
import com.lhkj.ct.base.enums.ReturnStatus;
import com.lhkj.ct.base.exception.BusinessException;
import com.lhkj.ct.base.utils.chart.JFreeChartConfig;
import com.lhkj.ct.base.utils.chart.JFreeChartUtil;
import com.lhkj.ct.base.utils.file.FileUtils;
import com.lhkj.ct.base.utils.file.word.xwpf.CustomXWPFDocument;
import com.lhkj.ct.base.utils.file.word.xwpf.ExportWord;
import com.lhkj.ct.meta.modules.psychology.model.vo.DimDistribution;
import com.lhkj.ct.meta.modules.psychology.model.vo.DimenStatistics;
import com.lhkj.ct.meta.modules.psychology.model.vo.GroupReportVo;
import com.lhkj.ct.meta.modules.report.AbstractReportHandle;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.jfree.data.category.DefaultCategoryDataset;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STJc;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STVerticalJc;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 *     导出团体报告
 * </p>
 */
public class ExportGroupReport extends AbstractReportHandle<GroupReportVo, XWPFDocument> {


    private final ExportWord word;

    public ExportGroupReport() {
        word = new ExportWord();
    }

    @Override
    public XWPFDocument generateReport(GroupReportVo repVo) {
        XWPFDocument document;
        // step 读取word模板
        try (InputStream is = FileUtils.readResourceFile("report\\团体报告模板.docx")){
            document = new CustomXWPFDocument(is);
        } catch (IOException e) {
            logger.error("团体报告模板加载失败");
            throw new BusinessException(ReturnStatus.SC_NOT_FOUND, "模板加载失败");
        }
        Map<String, Object> params = BeanUtil.beanToMap(repVo);
        // step word标题
        word.replaceInPara(document.getParagraphArray(0), params);
        // step 一、基本信息
        word.replaceInTable(document.getTableArray(0), params);
        // step 二、测验简介
        word.replaceInPara(document.getParagraphArray(3), params);
        // step 三、团队平均状态统计图
        String seriesKey = repVo.getScaleName();
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
        for (DimenStatistics dimenStatistics : repVo.getAvgList()) {
            dataset.addValue(dimenStatistics.getAvg(), seriesKey, dimenStatistics.getDimName());
        }
        JFreeChartConfig config = new JFreeChartConfig();
        // 标题
        config.setTitle(repVo.getScaleName());
        config.setValueAxisLabel("分数（分）");
        config.setWidth(600);
        config.setHeight(repVo.getAvgList().size() * 50 + 100);
        try {
            BufferedImage bi = JFreeChartUtil.drawHorizontalBarChart(config, dataset);
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            ImageIO.write(bi, "jpg", os);
            document.getParagraphArray(5).createRun().addPicture(new ByteArrayInputStream(os.toByteArray()), XWPFDocument.PICTURE_TYPE_JPEG, "",
                    Units.pixelToEMU(config.getWidth()), Units.pixelToEMU(config.getHeight()));
        } catch (Exception e) {
            logger.error("团体报告平均状态图表生成异常:{}", ExceptionUtils.getRootCauseMessage(e));
        }
        // step 三、团队平均状态表格
        List<List<Object>> avgList = repVo.getAvgList().stream().map(p -> {
            List<Object> list = new LinkedList<>();
            list.add(p.getDimName());
            list.add(p.getAvg());
            list.add(p.getStd());
            list.add(p.getMedian());
            list.add(p.getMax());
            list.add(p.getMin());
            return list;
//                Lists.newArrayList(p.get("MC"), p.get("AVG"), p.get("STD"),p.get("MEDIAN"), p.get("MAX"), p.get("MIN"))
        }).collect(Collectors.toList());
        XWPFTable avgTable = document.getTableArray(1);
        word.insertTable(avgTable, avgList, STJc.LEFT, STVerticalJc.CENTER);
        // step 四、人员分布统计图
        // 绘制条形图
        DefaultCategoryDataset avgDataSet = new DefaultCategoryDataset();
        for (DimDistribution map : repVo.getDistList()) {
            avgDataSet.addValue(map.getDistPercentValue(), map.getStatusName(), map.getDimName());
        }
        JFreeChartConfig avgChartConfig = new JFreeChartConfig();
        // 标题
        avgChartConfig.setTitle("分布比例");
        avgChartConfig.setWidth(640);
        avgChartConfig.setHeight(480);
        try {
            BufferedImage bi = JFreeChartUtil.drawPercentBarChart(avgChartConfig, avgDataSet);
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            ImageIO.write(bi, "jpg", os);
            document.getParagraphArray(8).createRun().addPicture(new ByteArrayInputStream(os.toByteArray()), XWPFDocument.PICTURE_TYPE_JPEG, "",
                    Units.pixelToEMU(640), Units.pixelToEMU(480));
        } catch (Exception e) {
            logger.error("团体报告人员分布图表生成异常:{}", ExceptionUtils.getRootCauseMessage(e));
        }
        // step 四、人员分布表格
        List<List<Object>> dist = repVo.getDistList().stream().map(p -> Lists.newArrayList((Object) p.getDimName(), p.getStatusName(), String.format("%d人(%s)",p.getCounts(), p.getDistPercent()) , p.getWarnPercent())).collect(Collectors.toList());
        XWPFTable distTable = document.getTableArray(2);
        word.insertTable(distTable, dist, STJc.CENTER, STVerticalJc.CENTER);
        int row = 1;
        Map<Object, Long> wdmc = repVo.getDistList().stream().collect(Collectors.groupingBy(DimDistribution::getDimName, Collectors.counting()));
        for (Long value : wdmc.values()) {
            word.getXwpfTableHelper().mergeCellsVertically(distTable, 0, row, value.intValue() + row - 1);
            word.getXwpfTableHelper().mergeCellsVertically(distTable, 3, row, value.intValue() + row - 1);
            row = row + value.intValue();
        }
        return document;
    }
}
